home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / PASCAL / 0189.ZIP / LOAN2.INC < prev    next >
Text File  |  1986-02-08  |  18KB  |  537 lines

  1.  
  2.   const  ACCEPT    = 'A';    { Action codes. }
  3.          MODIFY    = 'M';
  4.          PRINT     = 'P';
  5.  
  6.          VIDEO     = 'V';    { Output device codes. }
  7.          PRINTER   = 'P';
  8.  
  9.          MIN_LOAN  = 100.0;       { Program limits. }
  10.          MAX_LOAN  = 9999999.99;  { These values may be reset to }
  11.          MIN_RATE  = 0.0;         { impose stricter range checking. }
  12.          MAX_RATE  = 99.999;
  13.          MIN_PMT   = 5.00;
  14.          MAX_PMT   = 9999999.99;
  15.          MAX_TERM  = 360;         { Stated as number of payments. }
  16.          END_INP   = 16;          { Last user input field on LOAN.SCR }
  17.  
  18.   type  Full_Name   = record
  19.                         first_name      : Str_15;
  20.                         last_name       : Str_15;
  21.                         title           : Str_10;
  22.                       end;
  23.  
  24.         Loan_Record = record
  25.                         collateral    : Str_40;
  26.                         principle     : Real;
  27.                         rate          : Real;
  28.                         payment       : Real;
  29.                         pmts_per_yr   : Integer;
  30.                         first_mo      : Integer;
  31.                         first_yr      : Integer;
  32.                         no_of_pmts    : Real;
  33.                         select_yr     : Integer;
  34.                         out_dev       : Char;
  35.                         unused        : string[9];
  36.                       case commercial : Boolean of
  37.                           TRUE        : ( business_name : Str_40);
  38.                           FALSE       : ( borrower      : Full_Name);
  39.                       end;
  40.  
  41.   var    loan         : Loan_Record;
  42.          loan_file    : file of Loan_Record;
  43.          file_name    : File_ID;
  44.          inp_scrn     : Scrn;
  45.          fld_dat      : Inp_Parms;
  46.          action       : Char;
  47.          exit_flag,
  48.          modified     : Boolean;
  49.  
  50.   procedure Initialize;
  51.  
  52.     begin
  53.       ClrScr; Write('Initializing...');
  54.       FillChar(loan,SizeOf(loan),ZERO);
  55.       output_id := 'Video Screen';
  56.       help_flag := FALSE;
  57.       err_flag := FALSE;
  58.       esc_flag := FALSE;
  59.       quit_flag := FALSE;
  60.       exit_flag := FALSE;
  61.       modified := FALSE;
  62.       end_session := FALSE;
  63.       Load_Input_Scrn('LOAN.SCR',inp_scrn,fld_dat);
  64.       Load_Help_Text('LN-HELP.SCR');
  65.     end; { Intitialize }
  66.  
  67.   procedure Select_Loan_File;
  68.  
  69.     procedure Get_FileSpec(var file_name: File_ID);
  70.       const chr_set     : Printable_Char = [':','0'..'9','A'..'Z'];
  71.             ctrl_set    : Control_Char   = [CR,BS,QUIT];
  72.             cmd_fld     : Fld_Parms      =
  73.                            ( xloc        : 56;           { Column }
  74.                              yloc        : MSG_LINE;     { Row }
  75.                              fld_len     : 10;           { Length }
  76.                              fld_type    : UC_TEXT;      { Upper Case }
  77.                              exit_type   : MANUAL;       { <CR> Required }
  78.                              fld_msg     : '');          { None }
  79.  
  80.       var   inp_ok      : Boolean;
  81.  
  82.       function Valid_FileID: Boolean;
  83.         var  col_pos : Byte;
  84.  
  85.         begin
  86.           col_pos := Pos(':',inp_str);
  87.           if (col_pos = ZERO) and (inp_str[1] in ['A'..'Z']) then
  88.             Valid_FileID := TRUE
  89.           else
  90.             if (col_pos = 2) and (inp_str[3] in ['A'..'Z']) then
  91.               if (inp_str[1] in ['A'..'P']) then
  92.                  Valid_FileID := TRUE
  93.               else Valid_FileID := FALSE
  94.             else
  95.               Valid_FileID := FALSE;
  96.         end; { Valid_FileID }
  97.  
  98.       begin { Get_FileSpec }
  99.         esc_flag := FALSE;
  100.         inp_ok := FALSE;
  101.         ClrScr;
  102.         Repeat
  103.           Display_Prompt(CMD_LINE,'MSG',
  104.                'Up to 8 characters beginning with a letter. | ' +
  105.                 QUIT_KEY + 'to Exit');
  106.           Display_Prompt(MSG_LINE,'INP',
  107.                'Enter LOAN FILE NAME to be created or updated ==> ');
  108.           Init_Field(FILL_CHAR,cmd_fld);
  109.           Get_Field_Input(cmd_fld,chr_set,ctrl_set);
  110.           if (not esc_flag) then
  111.             if Valid_FileID then
  112.               begin
  113.                 inp_ok := TRUE;
  114.                 file_name := inp_str + '.LDT';
  115.               end
  116.             else
  117.               Disp_Error_Msg((inp_str + ' is not a valid file name.'));
  118.         Until (inp_ok or esc_flag);
  119.         GoToXY(1,CMD_LINE); ClrEol;
  120.       end; { Get_FileSpec }
  121.  
  122.     procedure Open_Loan_File(file_name: File_ID);
  123.       begin
  124.         Assign(loan_file,file_name);
  125. {$I-}
  126.         Reset(loan_file); io_status := IOresult;
  127.         if (io_status = ZERO) then
  128.           Read(loan_file,loan); io_status := IOresult;
  129. {$I+}
  130.         if (io_status <> ZERO) then
  131.           Disp_IO_Error(file_name);
  132.       end; { Open_Loan_File }
  133.  
  134.     procedure Make_New_File(file_name: File_ID);
  135.  
  136.       procedure Make_Loan_File;
  137.  
  138.       procedure Set_Default_Values;
  139.         begin
  140.           FillChar(loan,SizeOf(loan),ZERO);
  141.           with loan do
  142.           begin
  143.             principle    := MIN_LOAN;
  144.             rate         := MIN_RATE;
  145.             no_of_pmts   := 12;
  146.             first_mo     := 1;
  147.             first_yr     := 1980;
  148.             pmts_per_yr  := 12;
  149.             select_yr    := ZERO;
  150.             out_dev      := VIDEO;
  151.             commercial   := FALSE;
  152.           end;
  153.         end; { Set_Default_Values }
  154.  
  155.         begin
  156.           Assign(loan_file,file_name);
  157. {$I-}
  158.           Rewrite(loan_file); io_status := IOresult;
  159. {$I+}
  160.           if (io_status = ZERO) then
  161.             Set_Default_Values
  162.           else
  163.             Disp_IO_Error(file_name);
  164.         end; { Make_Loan_File }
  165.  
  166.       begin { Make_New_File }
  167.         Display_Prompt(CMD_LINE,'INP',
  168.                          'Do you want to create a NEW loan file? (Y/N) ==> ');
  169.         if (Valid_Key(['Y','N']) = 'Y') then
  170.           Make_Loan_File
  171.         else
  172.           esc_flag := TRUE;
  173.       end; { Make_New_File }
  174.  
  175.     begin { Select_Loan_File }
  176.       Get_FileSpec(file_name);
  177.       if (not esc_flag) then
  178.         if Exist(file_name) then
  179.           Open_Loan_File(file_name)
  180.         else
  181.           Make_New_File(file_name);
  182.       ClrScr;
  183.     end; { Select_Loan_File }
  184.  
  185.   function Current_Value(field: Byte): Str_80;
  186.     var num_str : Str_80;
  187.         len     : Byte;
  188.  
  189.     begin
  190.       Current_Value := NULL;
  191.       len := fld_dat[field].fld_len;
  192.       with loan, fld_dat[field] do
  193.       case field of
  194.             1       : if commercial then
  195.                         Current_Value :='X'
  196.                       else
  197.                         Current_Value := ' ';
  198.             2       : if commercial then
  199.                         Current_Value := business_name;
  200.             3       : if (not commercial) then
  201.                         Current_Value :='X'
  202.                       else
  203.                         Current_Value := ' ';
  204.             4       : if (not commercial) then
  205.                         Current_Value := borrower.last_name;
  206.             5       : if (not commercial) then
  207.                         Current_Value := borrower.first_name;
  208.             6       : if (not commercial) then
  209.                         Current_Value := borrower.title;
  210.             7       : Current_Value := collateral;
  211.             8       : begin
  212.                         Str(principle:len:2,num_str);
  213.                         Current_Value := num_str;
  214.                       end;
  215.             9       : begin
  216.                         Str(rate:len:3,num_str);
  217.                         Current_Value := num_str;
  218.                       end;
  219.             10      : begin
  220.                         Str(payment:len:2,num_str);
  221.                         Current_Value := num_str;
  222.                       end;
  223.             11      : begin
  224.                         Str(pmts_per_yr:len,num_str);
  225.                         Current_Value := num_str;
  226.                       end;
  227.             12      : begin
  228.                         Str(first_mo:len,num_str);
  229.                         if (first_mo < 10) then
  230.                           num_str[1] := '0';
  231.                         Current_Value := num_str;
  232.                       end;
  233.             13      : begin
  234.                         Str(first_yr:len,num_str);
  235.                         Current_Value := num_str;
  236.                       end;
  237.             14      : begin
  238.                         Str(no_of_pmts:len:2,num_str);
  239.                         Current_Value := num_str;
  240.                       end;
  241.             15      : begin
  242.                         Str(select_yr:len,num_str);
  243.                         Current_Value := num_str;
  244.                       end;
  245.             16      : Current_Value := out_dev;
  246.             17      : Current_Value :=
  247.                         Copy(file_name,1,(Pos('.',file_name) - 1));
  248.             18      : begin
  249.                         if ((no_of_pmts * payment) > 0.0) then
  250.                           begin
  251.                             Str((no_of_pmts * payment):len:2,num_str);
  252.                             Current_Value := num_str;
  253.                           end
  254.                         else
  255.                           Current_Value := '   Invalid';
  256.                       end;
  257.             19      : begin
  258.                         if ((no_of_pmts * payment - principle) > 0.0) and
  259.                            (rate > 0.0) then
  260.                           begin
  261.                             Str((no_of_pmts * payment - principle):len:2,
  262.                                  num_str);
  263.                             Current_Value := num_str;
  264.                           end
  265.                         else
  266.                           Current_Value := '   Invalid';
  267.                       end;
  268.       end; {case}
  269.     end; { Current_Value }
  270.  
  271.   procedure Disp_Field_Value(field: Byte);
  272.     var fld_str : Str_80;
  273.  
  274.     begin
  275.       fld_str := Current_Value(field);
  276.       if fld_str <> NULL then
  277.         with fld_dat[field] do
  278.         begin  { Display fld_str and clear to end of field. }
  279.           GoToXY(xloc,yloc); Write(fld_str);
  280.           Repeat_Char(SPACE,(fld_len - Length(fld_str)));
  281.         end
  282.       else
  283.         Init_Field(FILL_CHAR,fld_dat[field]);
  284.     end; { Disp_Field_Value }
  285.  
  286.   procedure Display_Current_Values;
  287.     var  fld_no  : Byte;
  288.  
  289.     begin
  290.       ClrScr; Disp_Input_Scrn(inp_scrn);
  291.       for fld_no := 1 to fld_cnt do
  292.         Disp_Field_Value(fld_no);
  293.     end; { Display_Current_Values }
  294.  
  295.   procedure Select_Action;
  296.     var   cmd_msg     : Str_80;
  297.  
  298.     begin
  299.       cmd_msg := 'Accept  |  Modify  |  Print  | ' + HELP_KEY +
  300.                  'HELP  | ' + QUIT_KEY + 'Exit';
  301.       Display_Prompt(CMD_LINE,'CMD',cmd_msg);
  302.       Display_Prompt(MSG_LINE,'INP'
  303.                        ,'Press a CMD: key to enter selection ==> ');
  304.       action := Valid_Key(['A','M','P',HELP,QUIT]);
  305.     end; { Select_Action }
  306.  
  307.   procedure Accept_Data;
  308.     begin
  309. {$I-}
  310.       Reset(loan_file);
  311.       io_status := IOresult;
  312.       if (io_status = ZERO) then
  313.         begin
  314.           Write(loan_file,loan);
  315.           io_status := IOresult;
  316.         end;
  317. {$I+}
  318.       if (io_status = ZERO) then
  319.         modified := FALSE
  320.       else
  321.         Disp_IO_Error(file_name);
  322.     end; { Accept_Data }
  323.  
  324. procedure Modify_Data(fld_no,last_fld: Byte);
  325.   var periodic_rate      : Real;
  326.  
  327.   function Payment_Amt: Real;
  328.     var cents,
  329.         pmt_amt,
  330.         int_factor : Real;
  331.  
  332.     function Rate_Factor: Real;
  333.       var i       : Byte;
  334.           adj,
  335.           accum,
  336.           factor  : Real;
  337.  
  338.       begin
  339.         accum := 1.0; factor := 1.0 + periodic_rate;
  340.         for i := 1 to Trunc(loan.no_of_pmts) do
  341.           accum := (accum / factor);
  342.         if Frac(loan.no_of_pmts) > 0.0 then
  343.           begin
  344.             adj := accum - (accum / factor);
  345.             adj := adj * Frac(loan.no_of_pmts);
  346.             accum := accum - adj;
  347.           end;
  348.         Rate_Factor := accum;
  349.       end; { Rate_Factor }
  350.  
  351.     begin { Payment_Amt }
  352.       with loan do
  353.       begin
  354.         int_factor := Rate_Factor;
  355.         if (int_factor = 1.0) then
  356.            pmt_amt := principle / no_of_pmts
  357.         else
  358.           pmt_amt := (principle * periodic_rate) / (1 - int_factor);
  359.         cents := Frac(pmt_amt);
  360.         Payment_Amt := pmt_amt - cents + (Round(cents * 100.0) * 0.01);
  361.       end;
  362.     end; { Payment_Amt }
  363.  
  364.   procedure Input_Field;
  365.     var parms          : Fld_Parms;
  366.         err_msg,
  367.         cmd_msg        : Str_80;
  368.         last_yr        : Integer;
  369.         len, i         : Byte;
  370.         was_commercial : Boolean;
  371.  
  372.     function Payment_Cnt: Real;
  373.       begin
  374.         with loan do
  375.           if (Ln((1.0 + periodic_rate)) = 0.0) then
  376.             Payment_Cnt := (principle / payment)
  377.           else
  378.             Payment_Cnt := -(Ln(1.0 - (principle * periodic_rate / payment))
  379.                            / Ln((1.0 + periodic_rate)));
  380.       end; { Payment_Cnt }
  381.  
  382.     procedure Get_Pmts_Per_Yr;
  383.       type Term_Set    = set of 1..52;
  384.  
  385.       const  pmt_terms : Term_Set = [1..4,6,12,24,26,52];
  386.  
  387.       begin
  388.         with loan do
  389.         begin
  390.           pmts_per_yr := (Valid_Int(parms,1,52));
  391.           if (pmts_per_yr in pmt_terms) then
  392.             begin
  393.               periodic_rate := rate / pmts_per_yr / 100.0;
  394.               if (payment > 0.0) and
  395.                  ((periodic_rate * principle) >= payment) then
  396.                 begin
  397.                   Disp_Error_Msg(
  398.                   'Payment amount insufficient to pay interest');
  399.                   direction := (-1);
  400.                 end;
  401.             end
  402.           else
  403.             begin
  404.               Disp_Error_Msg(
  405.               'Valid entries are 1 2 3 4 6 12 24 26 52');
  406.               direction := ZERO;
  407.             end;
  408.         end;
  409.       end; { Get_Pmts_Per_Yr }
  410.  
  411.     procedure Get_Select_Yr;
  412.  
  413.       function End_Yr: Integer;
  414.         var mo_cnt,
  415.             last_yr  : Integer;
  416.  
  417.         begin
  418.           with loan do
  419.           begin
  420.             if (pmts_per_yr * no_of_pmts) = 0.0 then
  421.               mo_cnt := ZERO
  422.             else
  423.               mo_cnt := Trunc(12 / pmts_per_yr * no_of_pmts + 0.99);
  424.             End_Yr := Trunc((mo_cnt + first_mo - 1) div 12 + first_yr);
  425.           end; {with}
  426.         end; { End_Yr }
  427.  
  428.       begin { Get_Select_Yr }
  429.         last_yr := End_Yr;
  430.         if (last_yr > ZERO) then
  431.           with loan do
  432.           begin
  433.             select_yr := (Valid_Int(parms,ZERO,last_yr));
  434.             if (select_yr > ZERO) and (select_yr < first_yr) then
  435.               begin
  436.                 Disp_Error_Msg('No payments due in year entered.');
  437.                 direction := ZERO;
  438.               end;
  439.           end; {with}
  440.       end; { Get_Select_Yr }
  441.  
  442.     begin { Input_Field }
  443.       default := Current_Value(fld_no);
  444.       Clear_Prompts;
  445.       cmd_msg := PREV_KEY + ' Prev Fld  | ' +
  446.                  CLEAR_KEY + ' Clear Fld  | ' +
  447.                  QUIT_KEY + ' Exit ';
  448.       Display_Prompt(CMD_LINE,'CMD',cmd_msg);
  449.       Display_Prompt(PROMPT_LINE,'MSG',fld_dat[fld_no].fld_msg);
  450.       Display_Prompt(MSG_LINE,ENTER_KEY,default);
  451.       parms := fld_dat[fld_no];
  452.       len := parms.fld_len;
  453.       Init_Field(FILL_CHAR,parms);
  454.       with loan do
  455.       case fld_no of
  456.           1    : begin
  457.                    was_commercial := commercial;
  458.                    inchr := Valid_Chr(parms,['X',SPACE]);
  459.                    commercial := (inchr = 'X');
  460.                    if (not commercial) then
  461.                      begin
  462.                        Init_Field(FILL_CHAR,fld_dat[2]);
  463.                        if was_commercial then
  464.                          FillChar(business_name,Length(business_name),ZERO);
  465.                        direction := 2;
  466.                      end;
  467.                  end;
  468.           2    : begin
  469.                    business_name := (Valid_Str(parms));
  470.                    if (direction = INCR) then
  471.                      begin
  472.                        direction  := 5;
  473.                        for i := 3 to 6 do
  474.                          Init_Field(FILL_CHAR,fld_dat[i]);
  475.                      end;
  476.                  end;
  477.           3    : begin
  478.                    Write('X'); direction := INCR;
  479.                  end;
  480.           4    : begin
  481.                    borrower.last_name := (Valid_Str(parms));
  482.                    if (direction = DECR) then
  483.                      direction := (-3);
  484.                  end;
  485.           5    : borrower.first_name := (Valid_Str(parms));
  486.           6    : borrower.title := (Valid_Str(parms));
  487.           7    : begin
  488.                    collateral := (Valid_Str(parms));
  489.                    if (commercial and (direction = DECR)) then
  490.                      direction := (-5);
  491.                  end;
  492.           8    : principle := (Valid_Real(parms,2,MIN_LOAN,MAX_LOAN));
  493.           9    : rate := (Valid_Real(parms,3,MIN_RATE,MAX_RATE));
  494.           10   : payment := (Valid_Real(parms,2,0.0,MAX_PMT));
  495.           11   : Get_Pmts_Per_Yr;
  496.           12   : first_mo := (Valid_Int(parms,1,12));
  497.           13   : begin
  498.                    first_yr := (Valid_Int(parms,1900,2040));
  499.                    if (payment > 0.0) and (direction = INCR) then
  500.                      begin
  501.                        no_of_pmts := Payment_Cnt;
  502.                        Disp_Field_Value(14);
  503.                        direction := 2;
  504.                      end;
  505.                  end;
  506.           14   : begin
  507.                    no_of_pmts :=
  508.                      (Valid_Real(parms,2,1.0,MAX_TERM));
  509.                    if (direction = INCR) then
  510.                      begin
  511.                        payment := Payment_Amt;
  512.                        Disp_Field_Value(10);
  513.                      end;
  514.                  end;
  515.           15   : Get_Select_Yr;
  516.           16   : out_dev := Valid_Chr(parms,['V','P']);
  517.         end; {case}
  518.         Disp_Field_Value(fld_no);  { Redisplay formated input }
  519.     end; { Input_Field }
  520.  
  521.   begin { Modify_Data }
  522.     repeat
  523.       Input_field;
  524.       fld_no := fld_no + direction;
  525.       if (fld_no < 1) then
  526.         fld_no := 1;
  527.     until (esc_flag or (fld_no > last_fld));
  528.     if esc_flag then
  529.       begin
  530.         esc_flag := FALSE;
  531.         with loan do
  532.           periodic_rate := rate / pmts_per_yr / 100.0;
  533.         loan.payment := Payment_Amt
  534.       end;
  535.     modified := TRUE;
  536.    end; { Modify_Data }
  537.